package org.springframework.social.connect.support;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.social.connect.ConnectionFactory;
import org.springframework.social.connect.ConnectionFactoryLocator;

public class ConnectionFactoryRegistry implements ConnectionFactoryLocator {
  private final Map<String, ConnectionFactory<?>> connectionFactories = new HashMap<>();
  
  private final Map<Class<?>, String> apiTypeIndex = new HashMap<>();
  
  public void addConnectionFactory(ConnectionFactory<?> connectionFactory) {
    if (this.connectionFactories.containsKey(connectionFactory.getProviderId())) {
      throw new IllegalArgumentException("A ConnectionFactory for provider '" + connectionFactory.getProviderId() + "' has already been registered");
    }
    this.connectionFactories.put(connectionFactory.getProviderId(), connectionFactory);
  }
  
  public void setConnectionFactories(List<ConnectionFactory<?>> connectionFactories) {
    for (ConnectionFactory<?> connectionFactory : connectionFactories) {
      addConnectionFactory(connectionFactory);
    }
  }
  
  public ConnectionFactory<?> getConnectionFactory(String providerId) {
    ConnectionFactory<?> connectionFactory = this.connectionFactories.get(providerId);
    if (connectionFactory == null) {
      throw new IllegalArgumentException("No connection factory for service provider '" + providerId + "' is registered");
    }
    return connectionFactory;
  }
  
  public <A> ConnectionFactory<A> getConnectionFactory(Class<A> apiType) {
    String providerId = this.apiTypeIndex.get(apiType);
    if (providerId == null) {
      throw new IllegalArgumentException("No connection factory for API [" + apiType.getName() + "] is registered");
    }
    return (ConnectionFactory)getConnectionFactory(providerId);
  }
  
  public Set<String> registeredProviderIds() {
    return this.connectionFactories.keySet();
  }
}
